//
//  JHAssetsGirdViewController.m
//  JHAssetsPhotoPickerViewController
//
//  Created by admin on 15/11/17.
//  Copyright © 2015年 mohe. All rights reserved.
//

#import "JHAssetsGirdViewController.h"
#import "UICollectionView+Convenience.h"
#import "JHAssetGirdViewCell.h"
#import "JHAssetsBrowserViewController.h"
#import "JHAssetsManager.h"
#import "PushAnimator.h"
#import <MBProgressHUD.h>
@interface JHAssetsGirdViewController ()<UINavigationControllerDelegate, JHAssetsSelectionDelegate>
{
    CGFloat _margin, _gutter, _columns;
    NSMutableArray *_selections;
}
@property (nonatomic) CGPoint initialContentOffset;
@property (nonatomic, strong) PHCachingImageManager *imageManager;
@property CGRect previousPreheatRect;

@end

@implementation JHAssetsGirdViewController

static NSString * const reuseIdentifier = @"Cell";
static CGSize AssetGridThumbnailSize;


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self updateCachedAssets];
    [self.collectionView reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.navigationController.delegate = self;
    [_toolBar setSelectedCount:[self photoBrowserDidSelectedCount]];
    [_toolBar setFrame:CGRectMake(0, self.view.frame.size.height-44, self.view.frame.size.width, 44)];
    [self.view addSubview:_toolBar];
}
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self resetCachedAssets];
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = NO;
    // Register cell classes
    [self.collectionView registerNib:[UINib nibWithNibName:@"JHAssetGirdViewCell" bundle:nil] forCellWithReuseIdentifier:reuseIdentifier];
    // Do any additional setup after loading the view.
    [self initialisation];
    UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc]initWithTitle:@"取消" style:UIBarButtonItemStylePlain target:self action:@selector(dismissPickViewController)];
    self.navigationItem.rightBarButtonItem = cancelItem;
    
    if(self.displaySelectionButtons){
        [self.collectionView setContentInset:UIEdgeInsetsMake(0, 0, 44, 0)];
        _toolBar = [[JHSelectionToolBar alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height-44, self.view.frame.size.width, 44)];
           [self.view addSubview:_toolBar];
    }
}
- (void)initialisation
{
    [self setupLayout];
    _selections = [NSMutableArray array];

    for (NSInteger i=0; i<self.assetResults.count; i++) {
        [_selections addObject:[NSNumber numberWithBool:NO]];
    }
    
    self.imageManager = [[PHCachingImageManager alloc] init];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/
#pragma mark getter
- (BOOL)displaySelectionButtons
{
    _displaySelectionButtons = self.setting.maxSelectCount>1;
    return _displaySelectionButtons;
}
- (CGSize)targetSize
{
   // return PHImageManagerMaximumSize;
    CGFloat scale = [UIScreen mainScreen].scale;
    return CGSizeMake(AssetGridThumbnailSize.width*scale, AssetGridThumbnailSize.height*scale);
}
- (NSInteger)photoBrowserDidSelectedCount
{
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF == %@",[NSNumber numberWithBool:YES]];
    NSInteger count = [_selections filteredArrayUsingPredicate:pred].count;
    return count;
}

#pragma mark - UINavigationControllerDelegate
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                            animationControllerForOperation:(UINavigationControllerOperation)operation
                                                         fromViewController:(UIViewController *)fromVC
                                                           toViewController:(UIViewController *)toVC
{
    if(operation == UINavigationControllerOperationPush)
        return [[PushAnimator alloc]init];
    [self.view addSubview:_toolBar];
    return nil;
}
#pragma mark <UICollectionViewDataSource>

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.assetResults.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    JHAssetGirdViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
    PHAsset *asset = self.assetResults[indexPath.item];
    cell.index = indexPath.item;
    cell.delegate = self;
    cell.representedAssetIdentifier = asset.localIdentifier;
    [cell.selectedButton setHidden:!self.displaySelectionButtons];
    [cell displaySelectionButton];
    [self.imageManager requestImageForAsset:asset
                                 targetSize:[self targetSize]
                                contentMode:PHImageContentModeAspectFill
                                    options:[JHAssetsManager thumbnailRequestOptions]
                              resultHandler:^(UIImage *result, NSDictionary *info) {
                                  // Set the cell's thumbnail image if it's still showing the same asset.
                                  if ([cell.representedAssetIdentifier isEqualToString:asset.localIdentifier]) {
                                      [cell.imgView setImage:result];
                                  }
                              }];
    return cell;
}


#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    JHAssetsBrowserViewController *vc = [[JHAssetsBrowserViewController alloc]init];
    if(self.displaySelectionButtons){
        vc.assetArray = [self.assetResults objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.assetResults.count)]];
    }else{
        vc.assetArray = [self.assetResults objectsAtIndexes:[NSIndexSet indexSetWithIndex:indexPath.item]];
    }
    vc.currentIndex = indexPath.item;
    vc.delegate = self;
    vc.displaySelectionButtons = self.displaySelectionButtons;
    self.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
    [self.navigationController pushViewController:vc animated:YES];
    [_toolBar setFrame:CGRectMake(0, self.view.frame.size.height-44, self.view.frame.size.width, 44)];
    vc.bottomBar = _toolBar;
    [self.navigationController.view addSubview:_toolBar];
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat margin = [self getMargin];
    CGFloat gutter = [self getGutter];
    CGFloat columns = [self getColumns];
    CGFloat value = floorf(((self.view.bounds.size.width - (columns - 1) * gutter - 2 * margin) / columns));
    AssetGridThumbnailSize = CGSizeMake(value, value);
    return AssetGridThumbnailSize;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return [self getGutter];
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return [self getGutter];
}

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    CGFloat margin = [self getMargin];
    return UIEdgeInsetsMake(margin, margin, margin, margin);
}
#pragma mark - Layout
- (void)setupLayout
{
    _columns = 4;
    _margin = 1, _gutter = 1;
    _initialContentOffset = CGPointMake(0, CGFLOAT_MAX);
}

- (CGFloat)getColumns {
    return _columns;
}

- (CGFloat)getMargin {
    return _margin;
}

- (CGFloat)getGutter {
    return _gutter;
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    // Update cached assets for the new visible area.
    [self updateCachedAssets];
}
#pragma mark - Asset Caching

- (void)resetCachedAssets {
    [self.imageManager stopCachingImagesForAllAssets];
    self.previousPreheatRect = CGRectZero;
}

- (void)updateCachedAssets {
    BOOL isViewVisible = [self isViewLoaded] && [[self view] window] != nil;
    if (!isViewVisible) { return; }
    
    // The preheat window is twice the height of the visible rect.
    CGRect preheatRect = self.collectionView.bounds;
    preheatRect = CGRectInset(preheatRect, 0.0f, -0.5f * CGRectGetHeight(preheatRect));
    
    /*
     Check if the collection view is showing an area that is significantly
     different to the last preheated area.
     */
    CGFloat delta = ABS(CGRectGetMidY(preheatRect) - CGRectGetMidY(self.previousPreheatRect));
    if (delta > CGRectGetHeight(self.collectionView.bounds) / 3.0f) {
        
        // Compute the assets to start caching and to stop caching.
        NSMutableArray *addedIndexPaths = [NSMutableArray array];
        NSMutableArray *removedIndexPaths = [NSMutableArray array];
        
        [self computeDifferenceBetweenRect:self.previousPreheatRect andRect:preheatRect removedHandler:^(CGRect removedRect) {
            NSArray *indexPaths = [self.collectionView aapl_indexPathsForElementsInRect:removedRect];
            [removedIndexPaths addObjectsFromArray:indexPaths];
        } addedHandler:^(CGRect addedRect) {
            NSArray *indexPaths = [self.collectionView aapl_indexPathsForElementsInRect:addedRect];
            [addedIndexPaths addObjectsFromArray:indexPaths];
        }];
        
        NSArray *assetsToStartCaching = [self assetsAtIndexPaths:addedIndexPaths];
        NSArray *assetsToStopCaching = [self assetsAtIndexPaths:removedIndexPaths];
        
        // Update the assets the PHCachingImageManager is caching.
        [self.imageManager startCachingImagesForAssets:assetsToStartCaching
                                            targetSize:[self targetSize]
                                           contentMode:PHImageContentModeAspectFill
                                               options:[JHAssetsManager thumbnailRequestOptions]];
        [self.imageManager stopCachingImagesForAssets:assetsToStopCaching
                                           targetSize:[self targetSize]
                                          contentMode:PHImageContentModeAspectFill
                                              options:[JHAssetsManager thumbnailRequestOptions]];
        
        // Store the preheat rect to compare against in the future.
        self.previousPreheatRect = preheatRect;
    }
}

- (void)computeDifferenceBetweenRect:(CGRect)oldRect andRect:(CGRect)newRect removedHandler:(void (^)(CGRect removedRect))removedHandler addedHandler:(void (^)(CGRect addedRect))addedHandler {
    if (CGRectIntersectsRect(newRect, oldRect)) {
        CGFloat oldMaxY = CGRectGetMaxY(oldRect);
        CGFloat oldMinY = CGRectGetMinY(oldRect);
        CGFloat newMaxY = CGRectGetMaxY(newRect);
        CGFloat newMinY = CGRectGetMinY(newRect);
        
        if (newMaxY > oldMaxY) {
            CGRect rectToAdd = CGRectMake(newRect.origin.x, oldMaxY, newRect.size.width, (newMaxY - oldMaxY));
            addedHandler(rectToAdd);
        }
        
        if (oldMinY > newMinY) {
            CGRect rectToAdd = CGRectMake(newRect.origin.x, newMinY, newRect.size.width, (oldMinY - newMinY));
            addedHandler(rectToAdd);
        }
        
        if (newMaxY < oldMaxY) {
            CGRect rectToRemove = CGRectMake(newRect.origin.x, newMaxY, newRect.size.width, (oldMaxY - newMaxY));
            removedHandler(rectToRemove);
        }
        
        if (oldMinY < newMinY) {
            CGRect rectToRemove = CGRectMake(newRect.origin.x, oldMinY, newRect.size.width, (newMinY - oldMinY));
            removedHandler(rectToRemove);
        }
    } else {
        addedHandler(newRect);
        removedHandler(oldRect);
    }
}

- (NSArray *)assetsAtIndexPaths:(NSArray *)indexPaths {
    if (indexPaths.count == 0) { return nil; }
    
    NSMutableArray *assets = [NSMutableArray arrayWithCapacity:indexPaths.count];
    for (NSIndexPath *indexPath in indexPaths) {
        PHAsset *asset = self.assetResults[indexPath.item];
        [assets addObject:asset];
    }
    
    return assets;
}


#pragma mark JHAssetsSelectionDelegate
- (BOOL)photoSelectionWithIndex:(NSInteger)index
{
    return [[_selections objectAtIndex:index] boolValue];
}
- (BOOL)photoCanSelected:(NSInteger)index
{
    if([self photoBrowserDidSelectedCount] == self.setting.maxSelectCount){
        NSString *message = [NSString stringWithFormat:@"您最多只能选择%li%@%@",self.setting.maxSelectCount, [self.setting unitDescribe], [self.setting assetsDescribe]];
        MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
        hud.mode = MBProgressHUDModeText;
        [hud setDetailsLabelFont:[UIFont systemFontOfSize:16]];
        hud.detailsLabelText = message;
        hud.removeFromSuperViewOnHide = YES;
        [hud hide:YES afterDelay:1.5];
        return NO;
    }
    return YES;
}
- (void)photoWithIndex:(NSInteger)index changeSelection:(BOOL)selection
{
    [_selections replaceObjectAtIndex:index withObject:[NSNumber numberWithBool:selection]];
    [_toolBar setSelectedCount:[self photoBrowserDidSelectedCount]];
}
- (void)didSelectedDone
{
    NSMutableArray *result = [NSMutableArray array];
    [_selections enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if([obj boolValue]){
            NSLog(@"%lu", (unsigned long)idx);
            [result addObject:[self.assetResults objectAtIndex:idx]];
        }
    }];
    if(self.picker.delegate && [self.picker.delegate respondsToSelector:@selector(photoPicker:didSelecteFiniehed:)]){
        [self.picker.delegate photoPicker:self.picker didSelecteFiniehed:result];
         [self.navigationController dismissViewControllerAnimated:YES completion:nil];
    }
}
- (NSInteger)photoDidSelectedCount
{
    return  [self photoBrowserDidSelectedCount];
}
- (void)dismissPickViewController
{
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
    if(self.picker.delegate && [self.picker.delegate respondsToSelector:@selector(photoPicker:didSelecteFiniehed:)]){
        [self.picker.delegate photoPicker:self.picker didSelecteFiniehed:nil];
    }
}
/*
// Uncomment this method to specify if the specified item should be highlighted during tracking
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
	return YES;
}
*/

/*
// Uncomment this method to specify if the specified item should be selected
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}
*/

/*
// Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
	return NO;
}

- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
	return NO;
}

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
	
}
*/

@end
